package com.oa.store.controller.workflow;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.spring.ProcessEngineFactoryBean;
import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.oa.store.util.Page;
import com.oa.store.util.PageUtil;
import com.oa.store.util.WorkflowUtils;

@Controller
@RequestMapping(value="/workflow")
public class ActivitiController {

	protected Logger logger = LoggerFactory.getLogger(getClass());
	 
	@Autowired
	ProcessEngineFactoryBean processEngine;
	
	@Autowired
	RepositoryService repositoryService;
	
	@RequestMapping(value="/process-list")
	public ModelAndView processList(HttpServletRequest request){
		ModelAndView mav = new ModelAndView("workflow/process-list");
		// 保存两个对象，一个是ProcessDefinition（流程定义），一个是Deployment（流程部署）
		List<Object[]> objects = new ArrayList<Object[]>();
		Page<Object[]> page = new Page<Object[]>(PageUtil.PAGE_SIZE);
		int[] pageParams = PageUtil.init(page, request);
		ProcessDefinitionQuery processDefinitionQuery= repositoryService.createProcessDefinitionQuery().orderByDeploymentId().desc();
		List<ProcessDefinition> processDefinitionList = processDefinitionQuery.listPage(pageParams[0], pageParams[1]);
		for(ProcessDefinition processDefinition : processDefinitionList){
			String deploymentId = processDefinition.getDeploymentId();
			Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult();
			objects.add(new Object[]{processDefinition,deployment});
		}
		page.setTotalCount(processDefinitionQuery.count());
		page.setResult(objects);
		mav.addObject("page",page);
		return mav;
	}
	
	@RequestMapping(value="/deploy")
	public String deploy(@Value("#{APP_PROPERTIES['export.diagram.path']}") String exportDir,@RequestParam(value="file",required = true) MultipartFile file){
		String fileName = file.getOriginalFilename();
		try{
			InputStream fileInputStream = file.getInputStream();
			Deployment deployment = null;
			//获得文件扩展名
			String extension = FilenameUtils.getExtension(fileName);
			if(extension.equals("zip")||extension.equals("bar")){
				ZipInputStream zip = new ZipInputStream(fileInputStream);
				deployment = repositoryService.createDeployment().addZipInputStream(zip).deploy();
			}else{
				deployment = repositoryService.createDeployment().addInputStream(fileName, fileInputStream).deploy();
			}
			List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).list();
		    for (ProcessDefinition processDefinition : list) {
                WorkflowUtils.exportDiagramToFile(repositoryService, processDefinition, exportDir);
            }
		}catch (Exception e) {
			logger.error("error on deploy process,because of file input stream",e);
		}
		return "redirect:/workflow/process-list";
	}
	
	@RequestMapping(value="/resource/read")
	public void loadByDeployment(@RequestParam("processDefinitionId") String processDefinitionId,@RequestParam("resourceType") String resourceType,HttpServletResponse response) throws Exception {
		ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
		String resourceName = "";
		if (resourceType.equals("image")) {
			resourceName = processDefinition.getDiagramResourceName();
		} else if (resourceType.equals("xml")) {
			resourceName = processDefinition.getResourceName();
		}
		InputStream resourceAsStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), resourceName);
		byte[] b = new byte[1024];
		int len = -1;
		while ((len = resourceAsStream.read(b, 0, 1024)) != -1) {
			response.getOutputStream().write(b, 0, len);
		}
	}
	
	/**
     * 删除部署的流程，级联删除流程实例
     *
     * @param deploymentId 流程部署ID
     */
    @RequestMapping(value = "/process/delete")
    public String delete(@RequestParam("deploymentId") String deploymentId) {
        repositoryService.deleteDeployment(deploymentId, true);
        return "redirect:/workflow/process-list";
    }
	

    /**
     * 挂起、激活流程实例
     */
    @RequestMapping(value = "processdefinition/update/{state}/{processDefinitionId}")
    public String updateState(@PathVariable("state") String state, @PathVariable("processDefinitionId") String processDefinitionId,
    		RedirectAttributes redirectAttributes) {
        if (state.equals("active")) {
            redirectAttributes.addFlashAttribute("message", "已激活ID为[" + processDefinitionId + "]的流程定义。");
            repositoryService.activateProcessDefinitionById(processDefinitionId, true, null);
        } else if (state.equals("suspend")) {
            repositoryService.suspendProcessDefinitionById(processDefinitionId, true, null);
            redirectAttributes.addFlashAttribute("message", "已挂起ID为[" + processDefinitionId + "]的流程定义。");
        }
        return "redirect:/workflow/process-list";
    }
    
    @RequestMapping(value = "/task/todo/list")
    @ResponseBody
    public List<Map<String, Object>> todoList(HttpSession session) throws Exception {
        List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
    	return result;
    }
    
}
